using System;
using System.Collections;
using System.Web.UI;
using PHSRAG.Insight21.CDS;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.FormsManagement;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.ScriptEngine;
using PHSRAG.Utility;
using BO = PHSRAG.Insight21.BusinessObjects;
using ScriptReference = PHSRAG.Insight21.ScriptEngine.ScriptReference;

namespace PHSRAG.Insight21.Humans
{
    /// <summary>
    /// Summary description for NewProcessPage.
    /// </summary>
    public partial class NewProcessPage : BasePage
    {
        #region constants

        private const string AdverseEventQuestionnaireName = "AdverseEventInitialQuestionnaire";
        private const string AmendmentQuestionnaireName = "AmendmentInitialQuestionnaire";
        private const string ContinuingReviewQuestionnaireName = "ContinuingReviewInitialQuestionnaire";
        private const string OtherEventQuestionnaireName = "OtherEventInitialQuestionnaire";
        private const string PageCacheKey = "newProcesPage_E4E00FC9-2A81-43fc-9EAE-ECB01B03B567";
        private const string ProcessTypeKey = "processType_E4E00FC9-2A81-43fc-9EAE-ECB01B03B567";
        private const string ProtocolAccessKey = "protocolAccessKey_E4E00FC9-2A81-43fc-9EAE-ECB01B03B567";
        private const string ProtocolIdKey = "protocolId_E4E00FC9-2A81-43fc-9EAE-ECB01B03B567";

        #endregion

        #region Private instance variables.

        private ICachePolicy applicationCachePolicy;
        private ICachePolicy cachePolicy;
        private string continuingReviewStudyType;
        private QuestionnaireVersion newProcessQuestionnaireVersion;
        private Hashtable pageCache;
        private ICachePolicy pageCachePolicy;
        private string processType;
        private int protocolId;
        private int userAccessLevel;

        #endregion

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                pageCache = pageCachePolicy.GetCachedObject(PageCacheKey) as Hashtable ?? new Hashtable();

                breadCrumb.Add(
                    "New Process",
                    Settings.GetKeyValue("SubModuleNavigation.Humans.NewProcessPageURL", ""),
                    Settings.GetKeyValue("BreadCrumb.DetailPageLevel", 2));

                annunciator.Message = string.Empty;

                if (!IsPostBack)
                {
                    cancelProcess.Attributes.Add("onKeyPress", "Save()");
                    Hashtable incomingPageHash =
                        cachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
                    if (incomingPageHash != null)
                    {
                        protocolId = (int) incomingPageHash[Keys.ProtocolIdKey];
                        processType = (string) (incomingPageHash[Keys.NewProcessTypeKey]);
                        userAccessLevel = Convert.ToInt32(incomingPageHash[Keys.ProtocolAccessKey]);

                        pageCache[ProtocolIdKey] = protocolId;
                        pageCache[ProcessTypeKey] = processType;
                        pageCache[ProtocolAccessKey] = userAccessLevel;

                        pageCachePolicy.Cache(PageCacheKey, pageCache);
                    }
                    else
                    {
                        protocolId = (int) pageCache[ProtocolIdKey];
                        processType = (string) (pageCache[ProcessTypeKey]);
                        userAccessLevel = (int) pageCache[ProtocolAccessKey];
                    }

                    switch (processType)
                    {
                        case Constants.ProtocolProcessType.Amendment:
                            processTitle.Text = "New Amendment";
                            newProcessQuestionnaireVersion = Questionnaire.GetActiveVersionByCategoryAndType(
                                cachePolicy,
                                FormsManagement.Constants.AmmendmentCategory.InitialQuestionnaire,
                                FormsManagement.Constants.QuestionnaireType.Amendment);
                            break;
                        case Constants.ProtocolProcessType.AdverseEvent:
                            processTitle.Text = "New Adverse Event";
                            newProcessQuestionnaireVersion = Questionnaire.GetActiveVersionByCategoryAndType(
                                cachePolicy,
                                FormsManagement.Constants.AdverseEventCategory.InitialQuestionnaire,
                                FormsManagement.Constants.QuestionnaireType.AdverseEvent);
                            break;
                        case Constants.ProtocolProcessType.ContinuingReview:
                            continuingReviewStudyType = (string) incomingPageHash[Keys.ContinuingReviewStudyTypeKey];

                            string continuingReviewFormName = string.Empty;

                            switch (continuingReviewStudyType)
                            {
                                case Constants.ContinuingReviewShortStudyType.InterventionInteraction:
                                    continuingReviewFormName =
                                        Settings.GetKeyValue(
                                            Constants.ContinuingReviewNameOverrideKey.InterventionInteraction,
                                            Constants.ContinuingReviewFormName.InterventionInteraction);
                                    break;
                                case Constants.ContinuingReviewShortStudyType.ExcessHumanMaterial:
                                    continuingReviewFormName =
                                        Settings.GetKeyValue(
                                            Constants.ContinuingReviewNameOverrideKey.ExcessHumanMaterial,
                                            Constants.ContinuingReviewFormName.ExcessHumanMaterial);
                                    break;
                                case Constants.ContinuingReviewShortStudyType.MedicalRecords:
                                    continuingReviewFormName =
                                        Settings.GetKeyValue(
                                            Constants.ContinuingReviewNameOverrideKey.MedicalRecords,
                                            Constants.ContinuingReviewFormName.MedicalRecords);
                                    break;
                                case Constants.ContinuingReviewShortStudyType.RPDR:
                                    continuingReviewFormName =
                                        Settings.GetKeyValue(
                                            Constants.ContinuingReviewNameOverrideKey.RPDR,
                                            Constants.ContinuingReviewFormName.RPDR);
                                    break;
                                case Constants.ContinuingReviewShortStudyType.SecondaryUse:
                                    continuingReviewFormName =
                                        Settings.GetKeyValue(
                                            Constants.ContinuingReviewNameOverrideKey.SecondaryUse,
                                            Constants.ContinuingReviewFormName.SecondaryUse);
                                    break;
                                case Constants.ContinuingReviewShortStudyType.Tissue:
                                    continuingReviewFormName =
                                        Settings.GetKeyValue(
                                            Constants.ContinuingReviewNameOverrideKey.TissueSample,
                                            Constants.ContinuingReviewFormName.TissueSample);
                                    break;
                            }

                            // case through the CR study type to select the appropriate QuestionnaireVersion...

                            processTitle.Text = "New Continuing Review";
                            newProcessQuestionnaireVersion = Questionnaire.GetActiveVersion(
                                cachePolicy,
                                continuingReviewFormName,
                                FormsManagement.Constants.QuestionnaireType.ContinuingReview);
                            break;
                        case Constants.ProtocolProcessType.OtherEvent:
                            processTitle.Text = "New Event";
                            newProcessQuestionnaireVersion = Questionnaire.GetActiveVersionByCategoryAndType(
                                cachePolicy,
                                FormsManagement.Constants.OtherEventCategory.InitialQuestionnaire,
                                FormsManagement.Constants.QuestionnaireType.OtherEvent);
                            break;
                        case Constants.AnimalProtocolProcessType.Amendment:
                            processTitle.Text = "New Amendment";
                            newProcessQuestionnaireVersion = Questionnaire.GetActiveVersionByCategoryAndType(
                                cachePolicy,
                                FormsManagement.Constants.AnimalsFormCatgory.Amendment,
                                FormsManagement.Constants.QuestionnaireType.Animals);
                            break;
                        case Constants.AnimalProtocolProcessType.AnnualReview:
                            processTitle.Text = "New Annual Review";
                            newProcessQuestionnaireVersion = Questionnaire.GetActiveVersionByCategoryAndType(
                                cachePolicy,
                                FormsManagement.Constants.AnimalsFormCatgory.AnnualReview,
                                FormsManagement.Constants.QuestionnaireType.Animals);
                            break;
                        case Constants.AnimalProtocolProcessType.TriennialReview:
                            processTitle.Text = "New Triennial Review";
                            newProcessQuestionnaireVersion = Questionnaire.GetActiveVersionByCategoryAndType(
                                cachePolicy,
                                FormsManagement.Constants.AnimalsFormCatgory.TriennialReview,
                                FormsManagement.Constants.QuestionnaireType.Animals);
                            break;
                        case Constants.AnimalProtocolProcessType.Deficiency:
                            processTitle.Text = "New Deficiency";
                            newProcessQuestionnaireVersion = Questionnaire.GetActiveVersionByCategoryAndType(
                                cachePolicy,
                                FormsManagement.Constants.AnimalsFormCatgory.Deficiency,
                                FormsManagement.Constants.QuestionnaireType.Animals);
                            break;
                    }

                    if (newProcessQuestionnaireVersion == null)
                    {
                        annunciator.Message = "No Initial Review Questionnaire exists. Please contact the Insight Help Desk.";
                        // hide the controls since there are no questions to answer.
                        questionnaireViewer.ContinueLoading = false;
                        questionnaireViewer.Visible = false;
                        saveProcess.Visible = false;
                    }
                    else
                    {
                        // pass this to teh Viewer control
                        questionnaireViewer.LoadQuestionnaire(newProcessQuestionnaireVersion, null);

                        // cache the QV
                        newProcessQuestionnaireVersion.Cache();
                    }
                }
                else
                {
                    protocolId = (int) pageCache[ProtocolIdKey];
                    processType = (string) (pageCache[ProcessTypeKey]);
                    userAccessLevel = (int) pageCache[ProtocolAccessKey];
                    newProcessQuestionnaireVersion = new QuestionnaireVersion(cachePolicy);
                    newProcessQuestionnaireVersion = (QuestionnaireVersion) cachePolicy.GetCachedObject(newProcessQuestionnaireVersion.CacheKey());
                }
                if (newProcessQuestionnaireVersion == null)
                {
                    annunciator.Message = "No Initial Review Questionnaire exists. Please contact the Insight Help Desk.";
                    // hide the controls since there are no questions to answer.
                    questionnaireViewer.ContinueLoading = false;
                    questionnaireViewer.Visible = false;
                }

                protocolDetailHeader.ProtocolID = protocolId;
            }
            catch (Exception ex)
            {
                annunciator.Message = ex.Message;
            }
        }

        /// <summary>
        /// Saves the new process
        /// </summary>
        /// <param name="sender">The control which raised the event.</param>
        /// <param name="e">Arguments assocoiated with the event</param>
        private void OnSaveProcessClick(object sender, ImageClickEventArgs e)
        {
            Protocol protocol = new Protocol(cachePolicy);
            UserContext userContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
            QuestionnaireAnswer initialRevAnswers = new QuestionnaireAnswer(cachePolicy);
            initialRevAnswers.LastModifiedByAdmPersonId = userContext.PersonId;

            object o = cachePolicy.GetCachedObject(protocol.CacheKey());
            if ((o != null) && (((Protocol) o).Id == protocolId))
            {
                protocol = (Protocol) o;
            }
            else
            {
                protocol.Load(DataAccess.GetConnectionString(), protocolId);
                cachePolicy.Cache(protocol.CacheKey(), protocol);
            }

            ProtocolProcess newProcess = null;
            initialRevAnswers.Name = newProcessQuestionnaireVersion.Questionnaire.Name;
            switch (processType)
            {
                case Constants.ProtocolProcessType.Amendment:
                    newProcess = protocol.GetNewProcess(ProtocolProcessType.Amendment, cachePolicy, DataAccess.GetConnectionString());
                    break;
                case Constants.ProtocolProcessType.AdverseEvent:
                    newProcess = protocol.GetNewProcess(ProtocolProcessType.AdverseEvent, cachePolicy, DataAccess.GetConnectionString());
                    break;
                case Constants.ProtocolProcessType.ContinuingReview:
                    newProcess = protocol.GetNewProcess(ProtocolProcessType.ContinuingReview, cachePolicy, DataAccess.GetConnectionString());
                    break;
                case Constants.ProtocolProcessType.OtherEvent:
                    newProcess = protocol.GetNewProcess(ProtocolProcessType.OtherEvent, cachePolicy, DataAccess.GetConnectionString());
                    break;
                case Constants.AnimalProtocolProcessType.Amendment:
                    newProcess = protocol.GetNewProcess(ProtocolProcessType.AnimalsAmendment, cachePolicy, DataAccess.GetConnectionString());
                    break;
                case Constants.AnimalProtocolProcessType.AnnualReview:
                    newProcess = protocol.GetNewProcess(ProtocolProcessType.AnimalsAnnualReview, cachePolicy, DataAccess.GetConnectionString());
                    break;
                case Constants.AnimalProtocolProcessType.Deficiency:
                    newProcess = protocol.GetNewProcess(ProtocolProcessType.AnimalsDeficiency, cachePolicy, DataAccess.GetConnectionString());
                    break;
                case Constants.AnimalProtocolProcessType.TriennialReview:
                    newProcess = protocol.GetNewProcess(ProtocolProcessType.AnimalsTriennialReview, cachePolicy, DataAccess.GetConnectionString());
                    break;
            }

            newProcess.SubmitterId = userContext.DomainUserId;
            newProcess.LastModifiedByUserId = userContext.DomainUserId;
            // set the submitter to the logged in user
            newProcess.SubmitterId = userContext.DomainUserId;
            // create a new ProtocolVersion since it's the first one.

            newProcess.LastModifiedDate = DateTime.Now;
            newProcess.Save(DataAccess.ConnectionString);

            ProtocolVersion currentVersion = newProcess.AddNewVersion(cachePolicy);
            currentVersion.Version = 1;

            newProcessQuestionnaireVersion = (QuestionnaireVersion) cachePolicy.GetCachedObject(newProcessQuestionnaireVersion.CacheKey());

            initialRevAnswers.QuestionnaireVersionId = newProcessQuestionnaireVersion.Id;
            currentVersion.QuestionnaireAnswers.Add(initialRevAnswers);

            //The following check will set the validation to true on the initial questionnaire only if the process is a initial review.
            if (newProcess.Type == Constants.AnimalProtocolProcessType.InitialReview ||
                newProcess.Type == Constants.ProtocolProcessType.InitialReview)
            {
                if (!questionnaireViewer.ValidateRequiredQuestions("All the questions have to be answered before the new protocol can be saved."))
                {
                    return;
                }
            }
            if (!questionnaireViewer.VerifyTextboxAnswers())
            {
                return;
            }
            questionnaireViewer.SaveQuestionnaire(initialRevAnswers);

            newProcess.VerifyRequiredAttachments(initialRevAnswers, ((RefCodes) applicationCachePolicy.GetCachedObject(RefCodes.CacheKey)), currentVersion);
            protocol.Save(DataAccess.ConnectionString);

            // now get the appropriate requirement Script from teh Questionnaire Version and run it, 
            // passing in the Protocol and QuestioinnaireAnswers as Intrinsics.
            Script requirementScript =
                (Script) newProcessQuestionnaireVersion.
                    Scripts[FormsManagement.Constants.ScriptType.Requirement];

            bool scriptError = false;

            if (requirementScript != null)
            {
                using (ScriptEngineHost scriptHost =
                    new ScriptEngineHost(
                        string.Format("{0}{1}", ScriptEngine.Constants.RootMoniker.RequirementScriptMoniker,
                            newProcessQuestionnaireVersion.Id),
                        ScriptEngine.Constants.RootNamespaces.RequirementScript, true))
                {
                    ArrayList refs = ScriptReference.GetAllScriptReferences(DataAccess.GetConnectionString());

                    for (int i = 0; i < refs.Count; ++i)
                    {
                        ScriptReference reference = (ScriptReference) refs[i];
                        scriptHost.AddDLLReference(reference.Path);
                    }

                    // add this protocol as an intrinsic.
                    scriptHost.AddIntrinsicObject("theProtocol", protocol);
                    // add the connection string
                    scriptHost.AddIntrinsicObject("connectionString", DataAccess.GetConnectionString());
                    // add the Process
                    scriptHost.AddIntrinsicObject(ScriptEngine.Constants.Instrinsics.ProtocolProcss, newProcess);
                    // add the version
                    // save the version to prevent future deadlocks
                    //			currentVersion.Save(DataAccess.ConnectionString);
                    scriptHost.AddIntrinsicObject("currentProtVersion", currentVersion);
                    // add the caching policy
                    scriptHost.AddIntrinsicObject("cachePolicy", cachePolicy);


                    try
                    {
                        if (scriptHost.Compile(requirementScript))
                        {
                            scriptHost.RunScript(requirementScript, "RequirementScript.Script", "Main");
                        }
                    }
                    catch (Exception ex)
                    {
                        scriptError = true;
                        string error = ex.Message;
                        error += ex.InnerException;
                        annunciator.Message = error;
                    }
                }
            }

            if (!scriptError)
            {
                // cache some things
                Hashtable outgoingData = new Hashtable();
                outgoingData.Add(Keys.ProtocolIdKey, protocolId);
                outgoingData.Add(Keys.ProtocolProcessIdKey, newProcess.Id);
                outgoingData.Add(Keys.ProtocolVersionNumberKey, currentVersion.Version);
                outgoingData.Add(Keys.ProtocolVersionIdKey, currentVersion.Id);
                outgoingData.Add(Keys.ProtocolAccessKey, userAccessLevel);
                pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);

                // cache the objects we'll need in the later pages
                protocol.Cache();
                newProcess.Cache();
                currentVersion.Cache();

                breadCrumb.Add(
                    "Work In Progress",
                    Settings.GetKeyValue("SubNavigation.Humans.WorkInProgressURL", ""),
                    Settings.GetKeyValue("BreadCrumb.SummaryPageLevel", 1));

                // now that it's saved, redirect the user to the ProtocolProcessOverview page.
                Page.Response.Redirect(
                    Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolProcessOverviewURL", ""));
            }
        }

        private void OnCancel(object sender, ImageClickEventArgs e)
        {
            Hashtable outgoingData = new Hashtable();
            outgoingData.Add(Keys.ProtocolIdKey, protocolId);
            outgoingData.Add(Keys.ProtocolAccessKey, userAccessLevel);
            pageCachePolicy.Cache(Keys.IncomingDataKey, outgoingData);

            Response.Redirect(Settings.GetKeyValue("SubModuleNavigation.Humans.ProtocolDetailsURL", ""));
        }

        #region Web Form Designer generated code

        protected override void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);
            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
            applicationCachePolicy = (Policy.ICachePolicy) Application[Policy.Names.ApplicationCachePolicyKey];
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.cancelProcess.Click += new ImageClickEventHandler(OnCancel);
            this.saveProcess.Click += new ImageClickEventHandler(OnSaveProcessClick);
        }

        #endregion
    }
}